/* cocos2d for iPhone
 *
 * http://code.google.com/p/cocos2d-iphone
 *
 * Copyright (C) 2008,2009 Ricardo Quesada
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the 'cocos2d for iPhone' license.
 *
 * You will find a copy of this license within the cocos2d for iPhone
 * distribution inside the "LICENSE" file.
 *
 */

// cocos2d
#import "special_effect.h"
//#include <blitz/applics.h>
#include <boost/random.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include "affine.h"
#include "ExTexture2D.h"
#include "cocos2d.h"

using namespace cocos2d;

Texture2D* getCombineTex(Texture2D *texture, CCSize win, boost::function<void()> callback)
{	
	const int MAX_TEX_SIZE = 512;
	//const int 
	cocos2d::CCTexture2DPixelFormat format = cocos2d::kTexture2DPixelFormat_RGBA8888;
	if (NULL == texture) {
		unsigned int width = 1;
		unsigned int height = 1;
		while (width < win.width) width *= 2;
		while (height < win.height) height *= 2;
		//ASSERT(width <= kTextureSize && height <= kTextureSize);
		
		ASSERT(width <= MAX_TEX_SIZE && height <= MAX_TEX_SIZE);
		void *data = malloc((int)(width * height * 4));
		memset(data, 0, (int)(width * height * 4));
		texture = new Texture2D();
		texture->initWithData(data, format, width, height, cocos2d::CCSize(win.width, win.height));
		free( data );
	}
	else {
		//ASSERT([texture pixelsWide] >= win.width && [texture pixelsHigh] >= win.height);
	}
	
	GLint  oldFBO;
	GLuint fbo;
	glGenFramebuffersOES(1, &fbo);	
	glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);
	
	// bind
	glBindFramebufferOES(GL_FRAMEBUFFER_OES, fbo);
	
	
	glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture->getName(), 0);
	
	// check if it worked (probably worth doing :) )
	GLuint status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
	if (status != GL_FRAMEBUFFER_COMPLETE_OES) ASSERT(0);
	
	GLfloat ClearColor[4];
	glGetFloatv(GL_COLOR_CLEAR_VALUE, ClearColor);
	
	glClearColor(0.0f,0.0f,0.0f,0.0f);
	glClear(GL_COLOR_BUFFER_BIT);
	
	GLfloat color[4];
	glGetFloatv(GL_CURRENT_COLOR, color);
	
	
	glColor4f(1.0f,1.0f,1.0f,1.0f);
	
	glMatrixMode(GL_MODELVIEW);
	GLfloat mat_model_view[16];
	glGetFloatv(GL_MODELVIEW_MATRIX, mat_model_view);
	glLoadIdentity();
	
	glMatrixMode(GL_PROJECTION);
	GLfloat mat[16];
	glGetFloatv(GL_PROJECTION_MATRIX, mat);
	glLoadIdentity();
	glViewport(0, 0, win.width, win.height);
	glOrthof(0, (float)win.width, 0, (float)win.height, 0, 100.0f);
	glScalef(1, -1, 1);
	glTranslatef(0, -win.height, 0);
	
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnableClientState (GL_VERTEX_ARRAY);
	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
	
	callback();
	
	glColor4f(color[0], color[1], color[2], color[3]);
	glClearColor(ClearColor[0], ClearColor[1], ClearColor[2], ClearColor[3]);
	
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glMultMatrixf(mat);
	glViewport(0, 0, 320, 480);
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glMultMatrixf(mat_model_view);
	
	glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);
	glDeleteFramebuffersOES(1, &fbo);
	return texture;	
}

namespace gauss_random {	
	
	typedef boost::minstd_rand base_generator_type;
	static base_generator_type generator(time(NULL));
	static boost::uniform_real<> uni_dist(0,1);
	static boost::variate_generator<base_generator_type, boost::uniform_real<> > uni(generator, uni_dist);
	template <typename result_type>
	result_type get_normal_distribution(result_type mean = 0, result_type sigma = 1)
	{		
		boost::normal_distribution<result_type> normal_distribution_generator(mean, sigma);
		return normal_distribution_generator(uni);
	}
	
	template <typename result_type>
	result_type get_uniform(result_type range)
	{
		return range * uni.operator()();
	}
};